package com.inspur.cloud.security;

import com.inspur.cloud.configuration.ApiConfig;
import com.inspur.cloud.entity.dataspace.UserEntity;
import com.inspur.cloud.enums.RoleEnum;
import com.inspur.cloud.security.exception.InvalidUsernamePasswordCombinationException;
import com.inspur.cloud.security.exception.LoginException;
import com.inspur.cloud.service.dataspace.LoginService;
import com.inspur.cloud.service.dataspace.UserManagerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashSet;
import java.util.Set;

@Component
public class UsernamePasswordAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserManagerService userManagerService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private LoginService loginService;
    @Autowired
    private ApiConfig apiConfig;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //是否配置了需要验证码
        boolean needVerifyCode = apiConfig.isVerifyCode();
        //只有登录接口需要验证码
        String url = request.getRequestURI();
        if(url==null || !url.contains("/login")){
            needVerifyCode=false;
        }
        if (needVerifyCode) {
            //需要验证码
            //检验验证码是否正确
            String code = request.getHeader("verifyCode");
            HttpSession session = request.getSession();
            String sessionCode;
            if (session != null) {
                sessionCode = session.getAttribute("verifyCode") + "";
            } else {
                sessionCode = "";
            }
            if (!sessionCode.equalsIgnoreCase(code)) {
                throw new LoginException("验证码不正确");
            }
        }
        if (authentication.getName() == null) {
            throw new InvalidUsernamePasswordCombinationException(null);
        }
        String username = authentication.getName().trim();
        UserEntity user = userManagerService.findByName(username);
        if (user == null) {
            throw new InvalidUsernamePasswordCombinationException(null);
        }
        //校验登录错误次数和密码时效
        loginService.checkLogin(user);
        if (authentication.getCredentials() == null) {
            throw new InvalidUsernamePasswordCombinationException(username);
        }
        String password = authentication.getCredentials().toString();
        if (!username.equals(user.getName()) || !passwordEncoder.matches(password, user.getPassword())) {
            throw new InvalidUsernamePasswordCombinationException(username);
        }
        //成功登陆，把错误次数清0
        user.setFailureTimes(0);
        userManagerService.save(user);
        return new ApiAuthentication(user, listUserGrantedAuthorities(user),true);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
    }

    /**
     * 设置角色
     * @param user
     * @return
     */
    private Set<GrantedAuthority> listUserGrantedAuthorities(UserEntity user) {
        Set<GrantedAuthority> authorities = new HashSet<>();
        if (RoleEnum.Admin.getValue().equals(user.getRole())) {
            authorities.add(new SimpleGrantedAuthority("ROLE_Admin"));
        }
        if (RoleEnum.Tenant.getValue().equals(user.getRole())) {
            authorities.add(new SimpleGrantedAuthority("ROLE_Tenant"));
        }
        if (RoleEnum.User.getValue().equals(user.getRole())) {
            authorities.add(new SimpleGrantedAuthority("ROLE_User"));
        }
        return authorities;
    }
}
